package math2;

import fem2.BasisManager;
import fem2.MeshPart;
import fem2.Node;

public class IsoparametricFaceGeometry extends IsoparametricGeometry {

	private static IsoparametricFaceGeometry instance = new IsoparametricFaceGeometry();

	private IsoparametricFaceGeometry() {
	}

	/**
	 * Get the instance of IsoparametricEdgeGeometry singleton
	 * 
	 * @return the Singleton instance
	 */
	public static IsoparametricFaceGeometry getInstance() {
		return instance;
	}

	@Override
	public double[][] jacobianAt(MeshPart mp, double... xi) {
		int dim = mp.getDimension();
		Node[] nodes = mp.getNodes();
		FunctionBasisOnRnToR basis = BasisManager.getInstance().getBasis(mp.getType());
		
		if (dim == 2) {
			double j11 = 0;
			double j12 = 0;
			double j21 = 0;
			double j22 = 0;
			for (int i = 0; i < nodes.length; i++) {
				FunctionRnToR Ni = basis.getBasisFunction(i);
				double[] dNi = Ni.gradientAt(xi);
				double[] X = nodes[i].getPosition();
				j11 += dNi[0] * X[0];
				j12 += dNi[0] * X[1];
				j21 += dNi[1] * X[0];
				j22 += dNi[1] * X[1];
			}
			return new double[][] { { j11, j12 }, { j21, j22 } };
		} else if (dim == 3) {
			double j11 = 0;
			double j12 = 0;
			double j13 = 0;
			double j21 = 0;
			double j22 = 0;
			double j23 = 0;
			for (int i = 0; i < nodes.length; i++) {
				FunctionRnToR Ni = basis.getBasisFunction(i);
				double[] dNi = Ni.gradientAt(xi);
				double[] X = nodes[i].getPosition();
				j11 += dNi[0] * X[0];
				j12 += dNi[0] * X[1];
				j13 += dNi[0] * X[2];
				j21 += dNi[1] * X[0];
				j22 += dNi[1] * X[1];
				j23 += dNi[1] * X[2];
			}
			return new double[][] { { j11, j12, j13 }, { j21, j22, j23 } };
		} else {
			throw new Error("invalid dimension");
		}
	}
}
